package network;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by sufutian on 2017/6/6.
 */

public class OkHttpEngine extends BaseDataSource implements INetworkDataSource, Callback {

    public final String TAG = "OkHttpEngine";
    /**
     * 服务器主机
     */
    private static String host = "https://goplay.1gospace.com/index.php?s=/Api";
    /**
     * 以json提交
     */
    MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    /**
     * 单列
     */
    private static OkHttpEngine insstance;
    /**
     * 接口地址
     */
    private String url;
    /**
     * 请求json
     */
    private IJson json;
    /**
     * okhttp实例
     */
    private static OkHttpClient httpClient;
    /**
     * 请求体
     */
    private RequestBody body;
    /**
     * 请求对象
     */
    private Request request;
    /**
     * 全局context
     */
    private static Context context;
    /**
     * 本地请求缓存 get有效
     */
    private static CacheControl cacheControl;
    /**
     * 请求类型
     */
    HTTP_TYPE http_type = HTTP_TYPE.GET;
    /**
     * 请求call
     */
    private Call call;

    private enum HTTP_TYPE {
        GET,
        POST_JSON,
        POST_FORM
    }

    public static String getHost() {
        return host;
    }

    /**
     * 设置服务器host
     *
     * @param host
     */
    public static void setHost(String host) {
        OkHttpEngine.host = host;
    }

    private OkHttpEngine() {
    }

    public static OkHttpEngine getOkHttp() {
        if (insstance == null) {
            synchronized (OkHttpEngine.class) {
                if (insstance == null) {
                    insstance = new OkHttpEngine();
                }
            }
        }
        return insstance;
    }

    /**
     * 应用启动时 初始化
     *
     * @param context
     */
    public void initOk(Context context) {
        this.context = context;
        String catchPath = Environment.getExternalStorageDirectory() + "/com.egospace.goplay";
        //缓存文件夹
        File cacheFile = new File(catchPath, "netcache");
        if (!cacheFile.exists()) {
            cacheFile.mkdirs();
        }
        //缓存大小为10M
        int cacheSize = 10 * 1024 * 1024;
        //创建缓存对象
        Cache cache = new Cache(cacheFile, cacheSize);//okhttp post是不能实现缓存的

        //设置缓存时间为60秒
        cacheControl = new CacheControl.Builder()
                .noTransform()
                .maxAge(60, TimeUnit.SECONDS)
                .build();

        httpClient = new OkHttpClient.Builder()
                .readTimeout(10 * 1000, TimeUnit.MILLISECONDS)//设置读取超时时间
                .writeTimeout(10 * 1000, TimeUnit.MILLISECONDS)//设置写的超时时间
                .connectTimeout(10 * 1000, TimeUnit.MILLISECONDS)//设置连接超时时间
                .cache(cache)
                .build();

    }

    /**
     * 开始连接网络
     */
    private void connect() {
        /**
         * 读取缓存
         */
        // TODO: 2017/6/7 读取缓存

        if (!isNetworkValidate()) {
            if (netListener != null) {
                netListener.onDataFail(DataSourceErrorType.network_error, "当前网络不可用", "");
            }
            return;
        }

        if (TextUtils.isEmpty(url)) {
            if (netListener != null) {
                netListener.onDataFail(DataSourceErrorType.parameter_error, "请设置url", "");
            }
            return;
        }

//        if (json == null) {
//            if (netListener != null) {
//                netListener.onDataFail(DataSourceErrorType.parameter_error, "请设置Json", "");
//            }
//            return;
//        }

//        if (httpClient != null&&call!=null) {//高并发 会返回失败
//            cancel();
//        }

        if (netListener != null) {
            netListener.onLoading();
            Log.e(TAG, "onLoading: ");
        }

        request(json, url, "");
    }

    /**
     * 处理并发起不同的请求
     *
     * @param json
     * @param url
     * @param tag
     * @return
     */
    private Request request(IJson json, String url, String tag) {
        Log.e(TAG, "request json: " + json);
        //TODO json串加密工作
        String completeUrl = host + url;

        Log.e(TAG, "requestUrl: " + completeUrl);
        try {
            Request.Builder requestBuilder = new Request.Builder()
                    .cacheControl(cacheControl)
                    .url(completeUrl)
                    .tag(tag);

            // TODO: 2017/6/7 get请求处理

            //post json
            if (http_type == HTTP_TYPE.POST_JSON) {
                RequestBody jsonbody = RequestBody.create(JSON, json.toString());
                requestBuilder.post(jsonbody);
            }
            //post表单
            if (http_type == HTTP_TYPE.POST_FORM && body != null) {
                requestBuilder.post(body);
            }
            this.request = requestBuilder.build();//建立请求
            httpClient.newCall(request).enqueue(this);//发起请求
        } catch (Exception e) {
            e.printStackTrace();
        }
        return request;
    }

    /**
     * 检查网络是否可用
     *
     * @return
     */
    private boolean isNetworkValidate() {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo netWorkInfo = cm.getActiveNetworkInfo();
            if (netWorkInfo != null) {
                return netWorkInfo.isAvailable();
            }
        }
        return false;
    }

    /**
     * 请求失败
     *
     * @param call
     * @param e
     */
    @Override
    public void onFailure(Call call, IOException e) {
        if (netListener != null) {
            netListener.onDataFail(DataSourceErrorType.network_error, "请求失败", "");
            Log.e(TAG, "onFailure: ");
        }
    }

    /**
     * 请求成功
     *
     * @param call
     * @param response
     * @throws IOException
     */
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (request == null || response == null || !response.isSuccessful()) {
            if (netListener != null) {
                netListener.onDataFail(DataSourceErrorType.network_error, "网络失败", "");
            }
        } else if (netListener != null) {
            int code = response.code();
            switch (code) {
                case 404:
                    netListener.onDataFail(DataSourceErrorType.network_error, "找不到服务器地址", "");
                    break;
                case 408:
                    netListener.onDataFail(DataSourceErrorType.network_error, "请求链接超时", "");
                    break;
                case 200:
                    try {

                        // TODO: 2017/6/7  返回数据解密

                        netListener.onDataComplete(response.body().string());

                        // TODO: 2017/6/7 写缓存

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }


    @Override/*BaseDataSource*/
    public void get() {
        http_type = HTTP_TYPE.GET;
        connect();
    }

    @Override/*BaseDataSource*/
    public void post() {
        http_type = HTTP_TYPE.POST_JSON;
        connect();
    }

    @Override
    public void postForm() {
        http_type = HTTP_TYPE.POST_FORM;
        connect();
    }


    @Override/*BaseDataSource*/
    public void cancel() {
        httpClient.dispatcher().cancelAll();//取消请求
    }

    @Override/*INetworkDataSource*/
    public void seturl(String server) {
        this.url = server;
    }

    @Override/*INetworkDataSource*/
    public void setJson(IJson json) {
        this.json = json;
    }

    @Override/*INetworkDataSource*/
    public void setBody(RequestBody body) {
        this.body = body;
    }
}
